// Copyright 2008 web2me.dev
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package net.web2me.parser;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import net.web2me.api.ParserException;
import net.web2me.util.DomUtil;
import net.web2me.util.Downloader;
import net.web2me.util.SiteStreamGenerator;
import net.web2me.util.UtilityException;

public class ImageBeaverParser extends AbstractBaseParser  {
	
	// http://www.imagefap.com/gallery.php?gid=823130
	
	private Logger logger = Logger.getLogger(this.getClass());
	
	private String imageStoreDir = "";
	
	List<String> otherPages = new ArrayList<String>();
	
	List<String> processedPages = new ArrayList<String>();
	
	private boolean firstCall = true;
	
	private Document document;
	
	public String getImageStoreDir() {
		return imageStoreDir;
	}

	public void setImageStoreDir(String imageStoreDir) {
		this.imageStoreDir = imageStoreDir;
	}

	public void process(String siteStream) throws ParserException {
		logger.info("Parsing ImageBeaver");
		
		try {
			document = DomUtil.generateDocument( siteStream );
		} catch (Exception e) {
			throw new ParserException(e);
		}
		
		NodeList links = document.getElementsByTagName("a");
		this.setImageStoreDir( buildDestinyDir( getDirName() ) );
		
		List<String> imagesLinks = new ArrayList<String>();
		List<String> rawImagesLink = new ArrayList<String>();
		
		logger.info("Scanning document for images");
		
		for( int i = 0; i < links.getLength(); i++){
			//Each link: http://www.imagebeaver.com/view.php?mode=gallery&g=534153&photo=1
			
			Element link = (Element)links.item(i);
			String href = "";
			
			if( ((href = link.getAttribute("href")).indexOf("&photo=") > -1)){
				if(!rawImagesLink.contains(href)){
					rawImagesLink.add(href);
					
					href= parseImageLink(href).replace(" ", "%20");
					imagesLinks.add(href);
				}
			}
		}
		
		Downloader downloader = new Downloader();
		downloader.setDestinyDirectory(imageStoreDir);
		
		if(imagesLinks.size() < 5){
			logger.info("Less than 5 images found. Downloading secuentially");
			for(String href: imagesLinks){
				downloader.setUrl(parseImageLink(href));
				try {
					downloader.download();
				} catch (UtilityException e) {
					logger.error("UtilityException caught", e);
					throw new ParserException("UtilityException caught", e);
				}
			}
		}else{
			Thread thread;
			List<Thread> threads = new ArrayList<Thread>();
			
			for(int i = 0; i < imagesLinks.size(); i++){
				downloader.setUrl(imagesLinks.get(i));
				
				logger.debug("Adding a new thread");
				
				thread = new Thread(downloader, imagesLinks.get(i));
				thread.run();
				
				threads.add(thread);
				
				while(threads.size() >= 5){
					for(Thread t: threads){
						if(!t.isAlive()){
							logger.debug("Removing thread: " + t.getName());
							threads.remove(t);
							break;
						}
					}
				}
			}
		}
		
		if( firstCall ){
			firstCall = false;
			
			for( String page: otherPages){
				String newPage = "";
				try {
					//logger.debug("Removing page: " + page);
					//otherPages.remove(page);
					newPage = SiteStreamGenerator.getStream(page);
				} catch (UtilityException e) {
					throw new ParserException(e);
				}
				
				this.process(newPage);
			}
		}
	}
	
	/**
	 * Stores the given image in the gallery directory
	 * @param imageUrl The URL of the image
	 * @throws ParserException
	 */
	private String parseImageLink(String imageUrl) throws ParserException{
		logger.info("Trying to save: " + imageUrl);
		
		String imagePage = "";
		try {
			imagePage = SiteStreamGenerator.getStream(imageUrl);
		} catch (UtilityException e) {
			logger.fatal("UtilityException caught", e);
			throw new ParserException(e);
		}
		
		Document imageDom;
		
		try {
			imageDom = DomUtil.generateDocument(imagePage);
		} catch (Exception e) {
			throw new ParserException(e);
		}
		
		//This one should work, but it doesn't
		//Element pic = imageDom.getElementById("thepic");
		
		NodeList imgs = imageDom.getElementsByTagName("img");
		Element pic = null;
		
		for(int i = 0; i < imgs.getLength(); i++){
			pic = (Element) imgs.item(i);
			
			if(pic.getAttribute("id") != null && "thepic".equals(pic.getAttribute("id"))){
				return pic.getAttribute("src");
			}
		}
		
		throw new ParserException("Could not find a picture on this page: " + imageUrl);
	}
	
	private String getDirName() throws ParserException{
		String galleryId;
		try {
			galleryId = SiteStreamGenerator.getQuery( getUrl() );
		} catch (UtilityException e) {
			throw new ParserException(e);
		}
		
		galleryId = galleryId.replace("mode=gallery&g=", "");
		
		return galleryId; 
	}
	
	private String buildDestinyDir(String dir){
		String tempDir = this.getDir() + "/" + dir;
		File finalDir = new File(tempDir);
		
		if(!finalDir.exists()){
			if(!finalDir.mkdirs()){
				logger.error("The directory " + tempDir + " could not be created");
			}else{
				logger.info("The directory " + tempDir + " has been created");
			}
		}else{
			logger.info("The directory " + tempDir + " already exists");
		}
		
		return tempDir;
	}

	public String getDescription() {
		return "Parses the ImageBeaver website";
	}

	public String getName() {
		return "ImageBeaver";
	}
}

